/*============================================================================*/
/*  ファイル : strlib.c                                                       */
/*  機能概要 : 文字列操作関数ソースファイル                                   */
/*  更新履歴 : 2011/01/20 新規作成                                            */
/*============================================================================*/
#include <stdio.h>
/* Include Files */
#include <string.h>
#include "memlib.h"
/* Defines */
/* Types */
/* External Functions */
/* External Variables */
/* Global Variables */
/* Local Variables */
/* Local Functions */
/*============================================================================*/
/*  名称     : strtail - 文字列末尾の'\0'位置を返す                           */
/*  呼出し   : string - 文字列                                                */
/*  戻り値   : 正常     : 文字列末尾のポインタ                                */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strtail( const char *string )
{
	/* input check */
	if (string == NULL) {
		return NULL;
	}

	return strchr(string, '\0');
}

/*============================================================================*/
/*  名称     : strshift - 文字列をoffsetだけ移動し、移動先ポインタを返す      */
/*  呼出し   : string - 文字列                                                */
/*             offset - 移動オフセット                                        */
/*  戻り値   : 正常     : 移動先のポインタ                                    */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strshift( char *string, size_t offset )
{
	/* Local Variables */
	char *s_pos = NULL;
	char *e_pos = NULL;

	/* input check */
	if (string == NULL) {
		return NULL;
	}

	/* set data */
	s_pos = string;
	e_pos = string + strlen(string);

	memmove(s_pos + offset, s_pos, e_pos - s_pos + 1);

	return string + offset;
}

/*============================================================================*/
/*  名称     : strreplace - 文字列の部分置換を行う                            */
/*  呼出し   : string - 文字列                                                */
/*             from   - 検索対象文字列                                        */
/*             to     - 置換後文字列                                          */
/*  戻り値   : 正常     : 置換後文字列のポインタ                              */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strreplace( char *string, const char *from, const char *to )
{
	/* Local Variables */
	int t_len = 0;			/* 置換する文字列長 */
	int f_len = 0;			/* 検索対象文字列長 */
	size_t offset = 0;		/* 置換後のサイズ差分 */
	char *s_pos = NULL;		/* 検索開始位置 */
	char *e_pos = NULL;		/* 文字列終端 */
	char *p = NULL;

	/* input check */
	if ((string == NULL) ||
	    (from == NULL) ||
	    (to == NULL)) {
		return NULL;
	}

	/* set data */
	t_len = strlen(to);
	f_len = strlen(from);
	offset = t_len - f_len;
	s_pos = string;
	e_pos = string + strlen(string);

	while (NULL != (p = strstr(s_pos, from)))
	{
		/* 置換領域の確保 */
		s_pos = strshift(p + f_len, offset);
		e_pos = e_pos + offset;

		/* 文字列の置換 */
		memmove(p, to, t_len);
	}

	return string;
}

/*============================================================================*/
/*  名称     : substr - 文字列の部分取得を行う                                */
/*  呼出し   : buffer - 取得データ書き込み先バッファ                          */
/*             string - 文字列                                                */
/*             s_pos  - 抜き出し開始位置                                      */
/*             e_pos  - 抜き出し終了位置                                      */
/*  戻り値   : 正常     : 取得データ書き込み先バッファ                        */
/*             引数異常 : NULL                                                */
/*  特記事項 : 取得文字列終端には'\0'が付加される                             */
/*============================================================================*/
char *substr( char *buffer, const char *string, int s_pos, int e_pos )
{

	/* input check */
	if ((buffer == NULL) ||
	    (string == NULL)) {
		return NULL;
	}

	if ((s_pos < 0) ||
	    (e_pos <= s_pos)) {
		return NULL;
	}

	memmove(buffer, (char *)(string + s_pos), (e_pos - s_pos));
	buffer[(e_pos - s_pos)] = '\0';

	return buffer;
}

/*============================================================================*/
/*  名称     : strreverse - 文字列の反転を行う                                */
/*  呼出し   : string - 文字列                                                */
/*  戻り値   : 正常     : 反転後文字列のポインタ                              */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strreverse( char *string )
{

	/* input check */
	if (string == NULL) {
		return NULL;
	}

	memreverse(string, strlen(string), sizeof(char));
	return string;

}

/*============================================================================*/
/*  名称     : strmatch - ワイルドカード可能な文字列比較を行う                */
/*  呼出し   : string - 被検索文字列                                          */
/*             find   - ワイルドカード含む検索文字列                          */
/*  戻り値   : 一致     :  1                                                  */
/*             不一致   :  0                                                  */
/*             引数異常 : -1                                                  */
/*============================================================================*/
int strmatch( const char *string, const char *find )
{

	/* input check */
	if ((string == NULL) ||
	    (find == NULL)) {
		return -1;
	}

	switch( *find ) {
		case '\0' :
			return '\0' == *string;
		case '*' :
			return (strmatch(string,  find + 1) ||
				(('\0' != *string) &&
				 strmatch(string + 1,  find)));
		case '?' :
			return (('\0' != *string) && 
				strmatch(string + 1,  find + 1));
		default :
			return (((unsigned char)*find == (unsigned char)*string) &&
				strmatch(string + 1, find + 1));
	}
}

/*============================================================================*/
/*  名称     : strstr - 文字列中の部分文字列の位置を探す                      */
/*  呼出し   : string - 被検索文字列                                          */
/*             find   - 検索文字列                                            */
/*  戻り値   : 正常     : 一致文字列のポインタ                                */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strstr( const char *string, const char *find )
{
	/* Local Variables */
	int slen;
	int flen;

	/* input check */
	if ((string == NULL) ||
	    (find == NULL)) {
		return NULL;
	}

	slen  = strlen(string);
	flen = strlen(find);

	while (slen >= flen) {
		if (memcmp(string, find, flen) == 0) {
			return (char *)string;
		}
	string++;
	slen--;
	}
	return NULL;
}

/*============================================================================*/
/*  名称     : strnstr - 文字列中の部分文字列の位置を探す                     */
/*  呼出し   : string - 被検索文字列                                          */
/*             find   - 検索文字列                                            */
/*             slen   - 検索する文字列数                                      */
/*  戻り値   : 正常     : 一致文字列のポインタ                                */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strnstr( const char *string, const char *find, size_t slen )
{

	/* Local Variables */
	char c, sc;
	size_t len;

	/* input check */
	if ((string == NULL) ||
	    (find == NULL) ||
	    (slen <= 0)) {
		return NULL;
	}

	if ((c = *find++) != '\0') {
	len = strlen(find);
		do {
			do {
				if ((slen -- < 1) ||
				    ((sc = *string++) == '\0')) {
					return NULL;
				}
			} while (sc != c);

			if (len > slen) {
				return NULL;
			}
		} while (strncmp(string, find, len) != 0);
		string--;
	}
	return (char *)string;
}

/*============================================================================*/
/*  名称     : strrstr - 文字列末尾から部分文字列の位置を探す                 */
/*  呼出し   : string - 被検索文字列                                          */
/*             find   - 検索文字列                                            */
/*  戻り値   : 正常     : 一致文字列のポインタ                                */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strrstr( char *string, const char *find )
{
	/* Local Variables */
	char *last = NULL;
	char *p = NULL;

	/* input check */
	if ((string == NULL) ||
	    (find == NULL)) {
		return NULL;
	}

	for( p = string; NULL != (p = strstr( p, find )); ++p ) {
		last = p;
		if ( '\0' == *p ) {
			return (char *)last;
		}
	}
	return (char *)last;
}

/*============================================================================*/
/*  名称     : strrnstr - 文字列末尾から部分文字列の位置を探す                */
/*  呼出し   : string - 被検索文字列                                          */
/*             find   - 検索文字列                                            */
/*             slen   - 検索する文字列数                                      */
/*  戻り値   : 正常     : 一致文字列のポインタ                                */
/*             引数異常 : NULL                                                */
/*============================================================================*/
char *strrnstr( char *string, const char *find , size_t slen )
{
	/* Local Variables */
	char *last = NULL;
	char *p = NULL;

	/* input check */
	if ((string == NULL) ||
	    (find == NULL) ||
	    (slen <= 0)) {
		return NULL;
	}

	for( p = string; NULL != (p = strnstr( p, find, slen - (p - string) )); ++p ) {
		last = p;
		if ( '\0' == *p ) {
			return (char *)last;
		}
	}
	return (char *)last;
}

